package org.yelongframework.json.gson.serializer.date;

import java.util.Date;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yelongframework.json.gson.adapter.DateTypeAdapter;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;

/**
 * 抽象的Json序列化的时间格式化
 * 
 * <pre>
 * class UserPojo {
 * 
 * 	private String username;
 * 
 * 	&#64;JsonAdapter(UserPojoAgeJsonAdapter.class)
 * 	private Integer age;
 * 
 * 	// nullSafe参数如果为true则值为空时不会调用适配器
 * 	&#64;JsonAdapter(value = JsonSerializerDateFormatYYYYMMDD.class, nullSafe = false)
 * 	private Date date;
 * 
 * 	private Date date2;
 * }
 * </pre>
 * 
 * @since 1.0.0
 */
public abstract class AbstractJsonSerializerDateFormat implements TypeAdapterFactory {

	private static final Logger log = LoggerFactory.getLogger(AbstractJsonSerializerDateFormat.class);

	/** 日期格式化模式 */
	private final String formatPattern;

	/** 日期类型适配器 */
	private final DateTypeAdapter dateTypeAdapter;

	// ==================================================构造器==================================================

	/**
	 * @param formatPattern 日期格式化模式
	 */
	public AbstractJsonSerializerDateFormat(String formatPattern) {
		this.formatPattern = Objects.requireNonNull(formatPattern, "formatPattern");
		dateTypeAdapter = new DateTypeAdapter();
		dateTypeAdapter.setFormatPattern(formatPattern);
	}

	// ==================================================创建==================================================

	@SuppressWarnings("unchecked")
	@Override
	public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
		if (!Date.class.isAssignableFrom(type.getRawType())) {
			return null;
		}
		TypeAdapter<Date> typeAdapter = gson.getAdapter(Date.class);
		if (!(typeAdapter instanceof DateTypeAdapter)) {
			return (TypeAdapter<T>) dateTypeAdapter;
		}
		// 如果gson中注册了DateTypeAdapter,则通过复制该适配器并修改format参数来实现，否则使用默认的适配器
		DateTypeAdapter dateTypeAdapter = (DateTypeAdapter) typeAdapter;
		if (formatPattern.equals(dateTypeAdapter.getFormatPattern())) {
			return (TypeAdapter<T>) dateTypeAdapter;
		}
		try {
			dateTypeAdapter = dateTypeAdapter.clone();
			dateTypeAdapter.setFormatPattern(formatPattern);
			return (TypeAdapter<T>) dateTypeAdapter;
		} catch (CloneNotSupportedException e) {
			log.debug("日期适配器克隆异常", e);
			return (TypeAdapter<T>) dateTypeAdapter;
		}
	}

	// ==================================================日期格式化模式==================================================

	/**
	 * @return 日期格式化模式
	 */
	public String getFormatPattern() {
		return formatPattern;
	}

}
